'use strict';

Object.defineProperty(exports, "__esModule", {
    value: true
});
/**
 * 复刻ES6 Promise
 * @param callback
 * @constructor
 */
function Promise(callback) {
    var _this = this;

    //默认初始化为pending
    this.state = this.STATE_PENDING;

    //resolve或reject时需要改变状态并把对应的参数传入
    //若Promise是同步resolve或reject，则要等到下一轮事件循环再执行（因要等待then的回调函数赋值）
    //若Promise是异步resolve或reject，则可以直接执行
    //关于setTimeout是下一轮事件循环再执行（若能在本轮事件结束时执行最好）
    var resolve = function resolve(arg) {
        _this.thenResolve ? _this.changeState(_this.STATE_RESOLVED, arg) : setTimeout(function () {
            _this.changeState(_this.STATE_RESOLVED, arg);
        }, 0);
    };
    var reject = function reject(arg) {
        _this.thenReject ? _this.changeState(_this.STATE_REJECTED, arg) : setTimeout(function () {
            _this.changeState(_this.STATE_REJECTED, arg);
        }, 0);
    };

    //马上执行
    callback(resolve, reject);
}

Promise.author = 'toffy';

/**
 * 静态变量
 */
Promise.prototype.STATE_PENDING = 'Pending';
Promise.prototype.STATE_RESOLVED = 'Resolved';
Promise.prototype.STATE_REJECTED = 'Rejected';

/**
 * promise状态改变事件
 * @param newState
 * @param arg
 */
Promise.prototype.changeState = function (newState, arg) {
    this.state = newState;

    if (newState == this.STATE_RESOLVED) {
        //有设置下一个then并且有包含第一个参数(resolve)时才需要把值继续传下去
        if (typeof this.thenResolve == 'function') {
            var thenReturnValue = this.thenResolve(arg);
            //then里面的返回值，注意区分普通类型和Promise类型
            if (thenReturnValue instanceof Promise) {
                //必须也要传nextPromiseReject，否则在then里return一个rejected promise将不会触发后面的catch方法
                thenReturnValue.then(this.nextPromiseResolve, this.nextPromiseReject);
            } else {
                //往后面一个then传值
                this.nextPromiseResolve(thenReturnValue);
            }
        }
    } else if (newState == this.STATE_REJECTED) {
        var promise = this;
        //如果当前promise没有设置reject函数，则一直往后面每个promise中找，直到找到有reject回调函数的
        while (typeof promise.thenReject != 'function' && promise.nextPromise) {
            promise = promise.nextPromise;
        }

        if (typeof promise.thenReject == 'function') {
            //找到了最近一个包含reject函数的promise
            promise.thenReject(arg);
        }
        //如果最后还是没找到reject则不会有任何反应
    }
};

/**
 * then里面主要为了设置nextPromiseResolve等回调函数名
 * @param resolveFunc
 * @param rejectFunc
 * @returns {Promise}
 */
Promise.prototype.then = function (resolveFunc, rejectFunc) {
    var _this2 = this;

    this.thenResolve = resolveFunc;
    this.thenReject = rejectFunc;

    //返回一个新的promise
    this.nextPromise = new Promise(function (resolve, reject) {
        //结果处理函数往下传
        _this2.nextPromiseResolve = resolve;
        _this2.nextPromiseReject = reject;
    });

    return this.nextPromise;
};

/**
 * 用于捕获错误(reject)的回调函数
 * @param rejectFunc
 * @returns {Promise|Promise.<T>}
 */
Promise.prototype.catch = function (rejectFunc) {
    return this.then(null, rejectFunc);
};

/**
 * 合并多个Promise实例，同时执行完后一起返回
 * @param promises
 * @returns {Promise}
 */
Promise.all = function (promises) {
    return new Promise(function (resolve, reject) {
        var resolveData = []; //正常返回值数组，注意顺序要跟promise一一对应
        var resolveCount = 0; //当前已经正常返回的个数，用于标识是否全部已正常返回
        var hasRejected = false;
        promises.forEach(function (promise, i) {
            Promise.resolve(promise).then(function (data) {
                resolveData[i] = data;
                resolveCount++;

                if (resolveCount == promises.length) {
                    //此时resolveData里的每一项也应该填满了
                    resolve(resolveData); //返回一个正常结果数组
                }
            }).catch(function (data) {
                //只要有一个被reject的话就直接reject，reject一次就够了
                if (!hasRejected) {
                    reject(data); //返回一个异常结果
                    hasRejected = true;
                }
            });
        });
    });
};

/**
 * 转换为Promise对象
 * @param obj
 * @returns {Promise}
 */
Promise.resolve = function (obj) {
    if (!obj) {
        //不带任何参数，直接返回一个Resolved状态的Promise对象
        return new Promise(function (resolve) {
            resolve();
        });
    } else {
        //Promise实例直接返回
        if (obj instanceof Promise) {
            return obj;
        } else if (typeof obj.then == 'function') {
            //参数是一个thenable对象（含方法then(resolve, reject)）
            return new Promise(obj.then);
        } else {
            //如果是其他情况则直接返回该参数
            return new Promise(function (resolve) {
                resolve(obj);
            });
        }
    }
};

/**
 * 转换为Promise对象
 * @param obj
 * @returns {Promise}
 */
Promise.reject = function (obj) {
    if (!obj) {
        //不带任何参数，直接返回一个Rejected状态的Promise对象
        return new Promise(function (resolve, reject) {
            reject();
        });
    } else {
        //Promise实例直接返回
        if (obj instanceof Promise) {
            return obj;
        } else if (typeof obj.then == 'function') {
            //参数是一个thenable对象（含方法then(resolve, reject)）
            return new Promise(obj.then);
        } else {
            //如果是其他情况则直接返回该参数
            return new Promise(function (resolve, reject) {
                reject(obj);
            });
        }
    }
};

//module.exports=Promise;
exports.default = Promise;